import * as http from 'http';
import { Server, Socket } from 'socket.io';
import { eventBus } from '../domain/service/eventBus';
import logger from '../common/logger';
import { AgentConnectedEvent } from '../domain/event/agentConnected';
import { AgentDisconnectedEvent } from '../domain/event/agentDisconnected';
import * as connectionManager from '../domain/service/connectionManager';
import { configurationService } from '../domain/service/configService';

const io = new Server({
  pingTimeout: configurationService.config.socketio.pingTimeout,
  pingInterval: configurationService.config.socketio.pingInterval
});

const nsp = io.of('/sim');

// socketio events should organized by module in future
export function init(server: http.Server) {
  io.attach(server);
  nsp.on('connection', (connection: Socket) => {
    const { identity, advertiseIp } = connection.handshake.query;
    logger.info(`agent(identity=${identity},ip=${advertiseIp}) connected(socket=${connection.id})`);
    connectionManager.addConnection(identity as string, connection);
    eventBus.emit(AgentConnectedEvent.NAME, new AgentConnectedEvent(identity as string));
    connection.on('disconnect', (reason: string) => {
      logger.info(`agent ${identity} disconnected(socket=${connection.id}): ${reason}`);
      connectionManager.deleteConnection(identity as string);
      eventBus.emit(AgentDisconnectedEvent.NAME, new AgentDisconnectedEvent(identity as string));
    });
    connection.on('simulation:log', ({ userId, appId, nodeId, jobId, content }) => {
      // save content to minio
      logger.info(JSON.stringify({ userId, appId, nodeId, jobId, content }, null, 4));
    });
  });
}